package com.jinyuanchun.learnjava;


import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import static com.jinyuanchun.learnjava.BeanUtils.bean2hash;
import static com.jinyuanchun.learnjava.BeanUtils.hash2Bean;

public class G2 {
    public static void main(String[] args) throws Exception {
        Cat cat = new Cat("tom",5,"shenzhen");
        Map<String, Object> hash = bean2hash(cat);
        for(String key : hash.keySet()){
            Object value = hash.get(key);
            System.out.println("key="+key+"\tvalue="+value);
        }
        Cat cat1 = hash2Bean(hash,Cat.class);
        System.out.println("===========\naddress : "+cat1.getAddress());
    }

}

class BeanUtils {
    public static <T,K,V> Map<String,Object> bean2hash(T bean) throws Exception,IllegalAccessException{
        if(bean == null){return null;}

        Map<String,Object> result = new HashMap<>();
        try{
            BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for(PropertyDescriptor property : propertyDescriptors){
                String key = property.getName();
                if(! key.equals("class")){
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(bean);
                    result.put(key,value);
                }
            }
        } catch (IntrospectionException e){
            e.printStackTrace();
        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e ){
            e.printStackTrace();
        }
        return result;
    }
    public static <T,K,V> T hash2Bean(Map<K,V>mp,Class<T> beanCls) throws Exception,IllegalArgumentException,InvocationTargetException{
        T t = null;
        try{
            BeanInfo beanInfo = Introspector.getBeanInfo(beanCls);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            t = beanCls.newInstance();
            for (PropertyDescriptor property : propertyDescriptors){
                String key = property.getName();
                if (mp.containsKey(key)){
                    Object value = mp.get(key);
                    Method setter = property.getWriteMethod();
                    setter.invoke(t,value);
                }
            }
        } catch (IntrospectionException e){
            e.printStackTrace();
        }
        return t;
    }
}

class Cat {
    private String name;
    private Integer age;
    private String address;

    public Cat(String name, Integer age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    public Cat(){
        this.name = null;
        this.age = null;
        this.address = null;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}